package com.trip.api;

import java.io.IOException;
import java.util.List;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;

import com.trip.config.AppUser;
import com.trip.config.CommonProperties;
import com.trip.exception.ServiceException;
import com.trip.service.FriendShipService;
import com.trip.service.UserService;
import com.trip.util.AuthUtil;
import com.trip.vo.PlaceAndExperienceListItemVo;
import com.trip.vo.SingleVo;
import com.trip.vo.UserSimpleVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.hibernate.validator.constraints.NotEmpty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

/**
 * Created by hc24 on 2017/10/5.
 */
@Api("User Api")
@RestController
@RequestMapping("user")
public class UserController {
    private static final Logger logger= LoggerFactory.getLogger(UserController.class);

    @Autowired
    private UserService userService;

    @Autowired
    private FriendShipService friendShipService;

    @Autowired
    private CommonProperties properties;

    @AppUser
    @ApiOperation("Edit nick name and intro")
    @RequestMapping(value = "",method = RequestMethod.PUT)
    public ControllerResult editNickName(@RequestHeader @ApiParam(name = "authToken", value = "Auth Token",required = true)String authToken,
                                         @RequestBody @NotNull EditUserRequest request){
        userService.update(AuthUtil.getUserId(authToken),request.getNickName(),request.getIntro());
        return ControllerResult.success();

    }

    @AppUser
    @ApiOperation("Query notes")
    @RequestMapping(value = "/notes",method = RequestMethod.GET)
    public ControllerResult<List<PlaceAndExperienceListItemVo>> queryNotes(@RequestHeader @ApiParam(name = "authToken", value = "Auth Token",required = true)String authToken){
        return ControllerResult.success( userService.queryNotes(AuthUtil.getUserId(authToken)));
    }

    @AppUser
    @ApiOperation("Change password")
    @RequestMapping(value = "/pwd",method = RequestMethod.PUT)
    public ControllerResult changePwd(@RequestHeader @ApiParam(name = "authToken", value = "Auth Token",required = true)String authToken,
                                      @RequestBody @Valid ChangePwdRequest pwdVo){
        userService.changePwd(AuthUtil.getUserId(authToken),pwdVo.getNewPassword(),pwdVo.getOldPassword());
        return ControllerResult.success();
    }

    @AppUser
    @ApiOperation(value="Upload cover",notes = "return cover picture's id")
    @RequestMapping(value = "/cover",method = RequestMethod.POST)
    public ControllerResult uploadCover(@RequestHeader @ApiParam(name = "authToken", value = "Auth Token",required = true)String authToken,
                                         @NotNull MultipartFile cover){
        logger.info("receive file:"+cover.getOriginalFilename());
        properties.validatePic(cover);
//       / FileUtils.writeByteArrayToFile(null,cover.getBytes());

        try {
            String coverPicId= userService.updateCover(AuthUtil.getUserId(authToken),cover.getBytes(),cover.getOriginalFilename().substring(cover.getOriginalFilename().indexOf(".")));
            return ControllerResult.success(coverPicId);
        } catch (IOException e) {
           throw new ServiceException("IO error,please retry");
        }


    }

    @AppUser
    @ApiOperation("Place or Experience visited")
    @RequestMapping(value = "/visited",method = RequestMethod.GET)
    public ControllerResult<List<PlaceAndExperienceListItemVo>> queryVisited(@RequestHeader @ApiParam(name = "authToken", value = "Auth Token",required = true)String authToken){
        Integer userId=AuthUtil.getUserId(authToken);
        return ControllerResult.success(userService.queryVisited(userId,userId));
    }

    @AppUser
    @ApiOperation("Query friends")
    @RequestMapping(value = "/friend",method = RequestMethod.GET)
    public ControllerResult<List<UserSimpleVo>> queryFriends(@RequestHeader @ApiParam(name = "authToken", value = "Auth Token",required = true)String authToken){
        return ControllerResult.success(userService.queryFriendList(AuthUtil.getUserId(authToken)));
    }

    @ApiOperation("Query user info")
    @RequestMapping(value = "/{userId}",method = RequestMethod.GET)
    public ControllerResult<UserSimpleVo> queryUser(@RequestHeader @ApiParam(name = "authToken", value = "Auth Token",required = false)String authToken,
            @PathVariable @NotNull Integer userId){
        Integer yourselfId=null;
        try{
            yourselfId=AuthUtil.getUserId(authToken);
        }catch(Exception e){}
        return ControllerResult.success(userService.queryUser(yourselfId,userId));
    }

    @ApiOperation("Query User visited Place or Experience ")
    @RequestMapping(value = "/{userId}/visited",method = RequestMethod.GET)
    public ControllerResult<List<PlaceAndExperienceListItemVo>> queryUserVisited(@RequestHeader @ApiParam(name = "authToken", value = "Auth Token",required = false)String authToken,
            @PathVariable @NotNull Integer userId){
        Integer yourselfId=null;
        try{
            yourselfId=AuthUtil.getUserId(authToken);
        }catch(Exception e){}
        return ControllerResult.success(userService.queryVisited(userId,yourselfId));
    }

    @AppUser
    @ApiOperation("Add friend")
    @RequestMapping(value = "/friend",method = RequestMethod.POST)
    public ControllerResult addFriend(@RequestHeader @ApiParam(name = "authToken", value = "Auth Token",required = true)String authToken,
                                      @NotNull @RequestBody SingleVo<Integer> friendId){
        friendShipService.addFriend(AuthUtil.getUserId(authToken),friendId.getValue());
        return ControllerResult.success();
    }

    @AppUser
    @ApiOperation("Remove friend")
    @RequestMapping(value = "/friend/{friendId}",method = RequestMethod.DELETE)
    public ControllerResult removeFriend(@RequestHeader @ApiParam(name = "authToken", value = "Auth Token",required = true)String authToken,
                                      @NotNull @PathVariable Integer friendId){
        friendShipService.removeFriend(AuthUtil.getUserId(authToken),friendId);
        return ControllerResult.success();
    }

    @AppUser
    @ApiOperation("Search Name/Email")
    @RequestMapping(value = "",method = RequestMethod.GET)
    public ControllerResult<List<UserSimpleVo>> queryUser(@RequestHeader @ApiParam(name = "authToken", value = "Auth Token",required = true)String authToken,
                                                          String param){
        return  ControllerResult.success(userService.queryUserList(AuthUtil.getUserId(authToken),param));
    }

    static class EditUserRequest{
        private String nickName;
        private String intro;

        public String getNickName() {
            return nickName;
        }

        public void setNickName(String nickName) {
            this.nickName = nickName;
        }

        public String getIntro() {
            return intro;
        }

        public void setIntro(String intro) {
            this.intro = intro;
        }
    }

    static class ChangePwdRequest {
        @NotEmpty
        private String oldPassword;
        @NotEmpty
        private String newPassword;

        public String getOldPassword() {
            return oldPassword;
        }

        public void setOldPassword(String oldPassword) {
            this.oldPassword = oldPassword;
        }

        public String getNewPassword() {
            return newPassword;
        }

        public void setNewPassword(String newPassword) {
            this.newPassword = newPassword;
        }
    }
}
